<?php

/**
 * 商城订单 下单逻辑
 * Created by PhpStorm.
 * @author 清凉Tea <973110519@qq.com>
 * Date: 2018/1/9
 * Time: 19:15
 */
namespace app\api\service;

use app\api\exception\AddressException;
use app\api\exception\ProductException;
use app\api\model\Address;
use app\api\model\ShopFreight;
use app\api\model\ShopOrder;
use app\api\model\ShopProduct;
use app\api\model\WechatCardCode;
use think\Db;
use think\Cache;

class OrderService
{
    //用户信息
    protected $userId;          //用户ID
    protected $openId;          //用户openID
    protected $addrId;          //联系地址ID
    protected $code;            //优惠券代码

    //订单商品 Id => 数量
    protected $orderList;
    protected $orderItem;
    protected $productList;

    /* 下单  */
    public function place($data)
    {
        //订单数据
        $this->openId = $data['openid'];
        $this->userId = $data['user_id'];
        $this->addrId = $data['addr_id'];
        $this->orderList = $data['products'];
        isset($data['decrypt_code']) && $this->code = $data['decrypt_code'];
        $status = $this->_getOrderStatus();
        // 开始创建订单
        $order = $this->_createOrder($status);
        return $order;
    }

    /*  获取卡券 折扣价格 */
    private function _getCouponPrice($totalPrice)
    {
        $couponPrice = 0;
        $wechatCard = new \app\mpbase\library\WechatCard();
        $res = $wechatCard->checkCode($this->code);
        if ($res['errcode'] == 0 && $res['errmsg'] == 'ok' && $res['can_consume']) {
            $card = WechatCardCode::where(['decrypt_code'=>$this->code])
                ->with('info')
                ->find();
            //存在卡券 并未过期
            if ($card != null && strtotime($card['end_time'])>=time()){
                //满减券
                if ($card['card_type'] == 'CASH' && $totalPrice >= $card['least_cost']) {
                    $couponPrice = $card['reduce_cost'];
                }
                //折扣券
                if ($card['card_type'] == 'DISCOUNT') {
                    $couponPrice = $totalPrice * (10 - $card['discount']) /10;
                }
            }
            //使用卡券
            if ($couponPrice > 0) {
                WechatCardCode::destroy(['decrypt_code'=>$this->code]);
                //支付回调 中删除卡券
//                $wechatCard->consumeCode($this->code);
            }
        }
        return $couponPrice;
    }

    /*  获取订单信息*/
    private function _getOrderStatus()
    {
        //获取 商品集合 ids
        $oPIds = array_column($this->orderList, 'pro_id');
        $this->productList = ShopProduct::getByIds($oPIds);

        //生成 订单信息
        $status = [
            'pro_count' => count($this->productList),
            'total_count' => 0,
            'order_item' => []
        ];
        $totalPrice = 0;
        foreach ($this->orderList as $orderItem) {
            $pStatus = $this->_getProductStatus(
                $orderItem['pro_id'], $orderItem['spec_id'], $orderItem['count']);
            $totalPrice += $pStatus['item_price'];
            $status['total_count'] += $pStatus['item_count'];
            array_push($status['order_item'], $pStatus);
        }
        $status['order_name'] = $status['order_item'][0]['pro_name'] . '/' . $status['order_item'][0]['spec_name']
            . ($status['pro_count'] == 1 ? '' : '等,共' . $status['pro_count'] . '种商品');
        $this->orderItem = $status['order_item'];
        //计算订单邮费
        $freIds = array_unique(array_column($this->productList, 'freight_id'));
        $status['orig_price'] = $totalPrice;
        $status['freight_price'] = ShopFreight::getPrice($freIds, $totalPrice);
        $status['coupon_price'] = $this->_getCouponPrice($totalPrice);
        $status['payment_price'] = $totalPrice + $status['freight_price'] - $status['coupon_price'];

        $status['contact'] = Address::getUserAddress($this->userId, $this->addrId);
        if (!$status['contact'])
            throw new AddressException();
        return $status;
    }

    /*  获取单个商品信息*/
    private function _getProductStatus($proId, $specId, $count)
    {
        $proList = $this->productList;
        $pIndex = -1;
        for ($i = 0; $i < count($proList); $i++) {
            if ($proId == $proList[$i]['id']) {
                $pIndex = $i;
                break;
            }
        }
        if ($pIndex == -1) {
            throw new ProductException();
        } else {
            $pro = $proList[$pIndex];
            $pStatus['pro_id'] = $pro['id'];
            $pStatus['pro_name'] = $pro['pro_name'];
            $pStatus['pro_img'] = $pro['pro_image'];
            $pStatus['spec_id'] = $specId;
            $pStatus['spec_name'] = $pro['spec_name'][$specId];
            $pStatus['spec_price'] = $pro['spec_price'][$specId];
            $pStatus['item_count'] = $count;
            $pStatus['item_price'] = $count * $pStatus['spec_price'];
            ShopProduct::addSaleNum($pro['id'], $count);
            return $pStatus;
        }
    }

    /*  生成订单记录.和订单商品记录*/
    private function _createOrder($status)
    {
        Db::transaction(function () use ($status, &$res) {
            $orderNo = self::generateOrderCode();
            $createTime = date('Y-m-d h:i:s', time());
            $data['mp_id'] = get_api_applet_id();
            $data['order_no'] = $orderNo;
            $data['openid'] = $this->openId;
            $data['user_id'] = $this->userId;
            $data['contact'] = $status['contact'];
            $data['order_name'] = $status['order_name'];
            $data['orig_price'] = $status['orig_price'];
            $data['payment_price'] = $status['payment_price'];
            $data['freight_price'] = $status['freight_price'];
            $data['coupon_price'] = $status['coupon_price'];
            $status['coupon_price'] > 0 && $data['coupon_code'] = $this->code;

            $order = ShopOrder::create($data);
            $order->shopOrderItems()->delete();
            $order->shopOrderItems()->saveAll($this->orderItem);
            $res = [
                'status' => 0,
                'order_id' => $order['id'],
                'order_no' => $orderNo,
                'create_time' => $createTime
            ];
        });
        return $res;
    }

    /*  生成订单编号*/
    public static function generateOrderCode()
    {
        date_default_timezone_set("PRC");
        $prefix = 'A' . chr(85 - date('m')) . chr(65 + date('d') % 26);
        $orderSn = $prefix . date('dd') . substr(time(), -4) . substr(microtime(), 2, 5) . sprintf(
                '%02d', rand(0, 99));
        return $orderSn;
    }
}